Set 1: CompletableFuture & Asynchronous Programming

1. What is CompletableFuture in Java?

CompletableFuture is a class in Java that provides an easy way to write asynchronous and non-blocking code.

2. How do you create a simple CompletableFuture?

Example:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello, World!");
future.thenAccept(System.out::println);
        

3. What is the difference between thenApply() and thenAccept()?

- thenApply(): Transforms the result and returns a new CompletableFuture.
- thenAccept(): Consumes the result without returning a new CompletableFuture.

4. How can you run multiple CompletableFutures in parallel?

Example:

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.allOf(future1, future2).join();
        

5. How do you handle exceptions in CompletableFuture?

Example using exceptionally():

CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Error!"); })
    .exceptionally(ex -> "Recovered from: " + ex.getMessage())
    .thenAccept(System.out::println);
        

6. What is the purpose of handle() in CompletableFuture?

handle() allows processing both the result and exception in a single callback.

7. How can you chain multiple CompletableFutures?

Example:

CompletableFuture.supplyAsync(() -> "Step 1")
    .thenApply(result -> result + " -> Step 2")
    .thenApply(result -> result + " -> Step 3")
    .thenAccept(System.out::println);
        

8. How do you run a CompletableFuture without returning a result?

Use runAsync():

CompletableFuture.runAsync(() -> System.out.println("Running asynchronously"));
        

9. What is the difference between join() and get()?

- get(): Throws checked exceptions.
- join(): Throws unchecked exceptions.

10. How do you combine results from two CompletableFutures?

Example using thenCombine():

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");
future1.thenCombine(future2, (a, b) -> a + " " + b)
    .thenAccept(System.out::println);
        

 

Set 2: CompletableFuture & Asynchronous Programming

11. What is the difference between supplyAsync() and runAsync()?

- supplyAsync(): Returns a result.
- runAsync(): Does not return a result.

12. How do you apply a transformation only if the CompletableFuture completes successfully?

Use thenApply():

CompletableFuture.supplyAsync(() -> "Success")
    .thenApply(result -> result + " processed")
    .thenAccept(System.out::println);
        

13. How do you apply an action only if the CompletableFuture fails?

Use exceptionally():

CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Error!"); })
    .exceptionally(ex -> "Recovered from: " + ex.getMessage())
    .thenAccept(System.out::println);
        

14. How do you apply an action after both CompletableFutures complete?

Use thenCombine():

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");
future1.thenCombine(future2, (a, b) -> a + " " + b)
    .thenAccept(System.out::println);
        

15. How do you apply an action after either CompletableFuture completes?

Use applyToEither():

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Fast Task");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Slow Task");
future1.applyToEither(future2, result -> "Result: " + result)
    .thenAccept(System.out::println);
        

16. How do you execute multiple CompletableFutures in sequence?

Use thenCompose():

CompletableFuture.supplyAsync(() -> "First Task")
    .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Second Task"))
    .thenAccept(System.out::println);
        

17. How do you execute multiple CompletableFutures concurrently and wait for all?

Use allOf():

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.allOf(future1, future2).join();
System.out.println("All tasks completed");
        

18. How do you execute multiple CompletableFutures and get the first completed result?

Use anyOf():

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Fast Task");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Slow Task");
CompletableFuture.anyOf(future1, future2)
    .thenAccept(result -> System.out.println("First completed: " + result));
        

19. How do you provide a default value if a CompletableFuture fails?

Use exceptionally():

CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Error!"); })
    .exceptionally(ex -> "Default Value")
    .thenAccept(System.out::println);
        

20. How do you ensure a cleanup action runs regardless of success or failure?

Use whenComplete():

CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Error!"); })
    .whenComplete((result, ex) -> System.out.println("Cleanup action executed"));
        

 

Set 3: CompletableFuture & Asynchronous Programming

21. How do you handle both success and failure scenarios in a CompletableFuture?

Use handle():

CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Failure!"); })
    .handle((result, ex) -> result != null ? result : "Recovered from: " + ex.getMessage())
    .thenAccept(System.out::println);
        

22. How do you add logging to a CompletableFuture without modifying the result?

Use thenAccept() or peek:

CompletableFuture.supplyAsync(() -> "Task Completed")
    .thenAccept(result -> System.out.println("Log: " + result));
        

23. How do you specify a timeout for a CompletableFuture?

Use completeOnTimeout():

CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(5000); } catch (InterruptedException e) { }
    return "Finished";
}).completeOnTimeout("Default Value", 3, TimeUnit.SECONDS)
  .thenAccept(System.out::println);
        

24. How do you cancel a CompletableFuture?

Use cancel():

CompletableFuture<String> future = new CompletableFuture<>();
future.cancel(true);
System.out.println("Future cancelled: " + future.isCancelled());
        

25. How do you create a completed CompletableFuture?

Use completedFuture():

CompletableFuture<String> future = CompletableFuture.completedFuture("Instant Result");
future.thenAccept(System.out::println);
        

26. How do you create a failed CompletableFuture?

Use failedFuture():

CompletableFuture.failedFuture(new RuntimeException("Something went wrong"))
    .exceptionally(ex -> "Handled: " + ex.getMessage())
    .thenAccept(System.out::println);
        

27. How do you convert a synchronous method into an asynchronous CompletableFuture?

Use supplyAsync():

public CompletableFuture<Integer> asyncMethod() {
    return CompletableFuture.supplyAsync(() -> compute());
}
private int compute() { return 42; }
        

28. How do you execute a task asynchronously without returning a result?

Use runAsync():

CompletableFuture.runAsync(() -> System.out.println("Task running"));
        

29. How do you execute a CompletableFuture using a custom thread pool?

Pass an ExecutorService:

ExecutorService executor = Executors.newFixedThreadPool(5);
CompletableFuture.supplyAsync(() -> "Using custom executor", executor)
    .thenAccept(System.out::println);
        

30. How do you execute a sequence of CompletableFutures with different return types?

Use thenCompose():

CompletableFuture.supplyAsync(() -> 10)
    .thenCompose(num -> CompletableFuture.supplyAsync(() -> "Result: " + num))
    .thenAccept(System.out::println);
        

 

Set 4: CompletableFuture & Asynchronous Programming

31. How do you combine multiple CompletableFutures into one result?

Use thenCombine() or thenCombineAsync():

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");
future1.thenCombine(future2, (a, b) -> a + " " + b)
    .thenAccept(System.out::println);
        

32. How do you handle timeouts for multiple asynchronous tasks?

Use anyOf() and then manually handle timeouts:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.anyOf(task1, task2).get(2, TimeUnit.SECONDS);
        

33. How do you handle exceptions in a CompletableFuture chain?

Use exceptionally() or handle():

CompletableFuture.supplyAsync(() -> { throw new RuntimeException("Error!"); })
    .exceptionally(ex -> "Error handled")
    .thenAccept(System.out::println);
        

34. What happens when you use get() on a CompletableFuture?

The get() method blocks the thread until the result is available, or an exception is thrown:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
String result = future.get();  // Blocks until result is available
System.out.println(result);
        

35. How do you chain multiple asynchronous actions using CompletableFuture?

Use thenApply() or thenCompose():

CompletableFuture.supplyAsync(() -> "Task 1")
    .thenApply(result -> result + " -> Task 2")
    .thenApply(result -> result + " -> Task 3")
    .thenAccept(System.out::println);
        

36. How do you wait for multiple futures to complete and handle the results?

Use allOf():

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.allOf(future1, future2).join();
System.out.println("All tasks completed");
        

37. What is the difference between thenApply() and thenCompose() in CompletableFuture?

thenApply() applies a function to the result, returning a new result.
thenCompose() applies a function returning another CompletableFuture and flattens it:

CompletableFuture.supplyAsync(() -> "Task")
    .thenApply(result -> result + " Completed")
    .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " and Finished"))
    .thenAccept(System.out::println);
        

38. How do you create a delayed CompletableFuture?

Use sleep() within a supplyAsync task:

CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(3000); } catch (InterruptedException e) { }
    return "Delayed Result";
}).thenAccept(System.out::println);
        

39. How do you execute tasks asynchronously without returning any result?

Use runAsync():

CompletableFuture.runAsync(() -> {
    System.out.println("Asynchronous Task without result");
});
        

40. How do you transform the result of a CompletableFuture?

Use thenApply() to modify the result:

CompletableFuture.supplyAsync(() -> "Initial Result")
    .thenApply(result -> result + " -> Transformed")
    .thenAccept(System.out::println);
        

 

Set 5: CompletableFuture & Asynchronous Programming

41. How do you chain multiple tasks that depend on the result of the previous task?

Use thenCompose() to flatten nested CompletableFutures:

CompletableFuture.supplyAsync(() -> "Task 1")
    .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Task 2"))
    .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Task 3"))
    .thenAccept(System.out::println);
        

42. How do you cancel an ongoing asynchronous task?

Use cancel() on the CompletableFuture instance:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(5000); } catch (InterruptedException e) { }
    return "Completed";
});
future.cancel(true); // Cancels the task
System.out.println("Cancelled: " + future.isCancelled());
        

43. How do you execute multiple tasks in parallel and collect the results?

Use allOf() or anyOf() to execute tasks and collect results:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.allOf(task1, task2).join();
task1.thenAccept(result -> System.out.println("Result: " + result));
task2.thenAccept(result -> System.out.println("Result: " + result));
        

44. How do you execute an action when any of the tasks completes?

Use anyOf() to execute an action when any task completes:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.anyOf(task1, task2)
    .thenAccept(result -> System.out.println("Completed: " + result));
        

45. How do you execute a sequence of tasks asynchronously, with each task dependent on the result of the previous?

Use thenCompose() to chain dependent tasks:

CompletableFuture.supplyAsync(() -> "Task 1")
    .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Task 2"))
    .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Task 3"))
    .thenAccept(System.out::println);
        

46. How do you convert a synchronous method to asynchronous using CompletableFuture?

Use supplyAsync() to convert:

public CompletableFuture<String> asyncMethod() {
    return CompletableFuture.supplyAsync(() -> syncMethod());
}
public String syncMethod() {
    return "Synchronous Method Result";
}
        

47. How do you handle a case where a CompletableFuture times out?

Use exceptionally() or handle() to provide a fallback:

CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(3000); } catch (InterruptedException e) { }
    return "Result";
})
.completeOnTimeout("Timeout Occurred", 2, TimeUnit.SECONDS)
.thenAccept(System.out::println);
        

48. How do you combine multiple independent tasks into a result?

Use thenCombine() to combine results:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
task1.thenCombine(task2, (result1, result2) -> result1 + " " + result2)
    .thenAccept(System.out::println);
        

49. How do you run an asynchronous task but don't care about the result?

Use runAsync() to execute a task without expecting a result:

CompletableFuture.runAsync(() -> System.out.println("Task running asynchronously"));
        

50. How do you handle multiple futures and get the first completed result?

Use anyOf() to get the first completed result:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.anyOf(task1, task2)
    .thenAccept(result -> System.out.println("First completed: " + result));
        

 

Set 6: CompletableFuture & Asynchronous Programming

51. How can you handle exceptions in CompletableFuture using a fallback method?

Use handle() or exceptionally() to handle exceptions and provide a fallback:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (true) throw new RuntimeException("Error");
    return "Success";
});
future.handle((result, ex) -> {
    if (ex != null) {
        return "Fallback due to error: " + ex.getMessage();
    }
    return result;
}).thenAccept(System.out::println);
        

52. How do you chain a series of asynchronous tasks where each task depends on the result of the previous task?

Use thenCompose() for task chaining:

CompletableFuture.supplyAsync(() -> "Task 1")
    .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Task 2"))
    .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Task 3"))
    .thenAccept(System.out::println);
        

53. How do you combine multiple independent asynchronous tasks into a single result?

Use thenCombine() to combine two tasks:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
task1.thenCombine(task2, (result1, result2) -> result1 + " " + result2)
    .thenAccept(System.out::println);
        

54. How can you execute a task after another task completes, regardless of whether it completed successfully or with an exception?

Use whenComplete() to execute a task after the completion of another:

CompletableFuture.supplyAsync(() -> "Task 1")
    .whenComplete((result, ex) -> {
        if (ex != null) {
            System.out.println("Error occurred: " + ex.getMessage());
        } else {
            System.out.println("Completed: " + result);
        }
    })
    .thenAccept(System.out::println);
        

55. How do you create a CompletableFuture that executes a task asynchronously?

Use supplyAsync() or runAsync() to execute tasks asynchronously:

CompletableFuture.supplyAsync(() -> "Asynchronous Task");
CompletableFuture.runAsync(() -> System.out.println("Running asynchronously"));
        

56. How do you block the current thread until a CompletableFuture completes?

Use join() or get() to block the current thread:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Task completed");
String result = future.join(); // Blocks until completion
System.out.println(result);
        

57. How do you run multiple independent tasks and wait for all of them to complete?

Use CompletableFuture.allOf() to wait for all tasks:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.allOf(task1, task2).join();
task1.thenAccept(result -> System.out.println("Result: " + result));
task2.thenAccept(result -> System.out.println("Result: " + result));
        

58. How do you perform a task only after another CompletableFuture has finished?

Use thenRun() to execute a task after another one completes:

CompletableFuture.supplyAsync(() -> "Task 1")
    .thenRun(() -> System.out.println("Task 1 finished, executing Task 2"));
        

59. How do you use a timeout to cancel an ongoing task?

Use completeOnTimeout() to set a timeout for a task:

CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(5000); } catch (InterruptedException e) { }
    return "Completed";
})
.completeOnTimeout("Timeout Occurred", 2, TimeUnit.SECONDS)
.thenAccept(System.out::println);
        

60. How do you handle multiple futures and get the result from the first one that completes?

Use anyOf() to get the first completed result:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.anyOf(task1, task2)
    .thenAccept(result -> System.out.println("First completed: " + result));
        

 

Set 7: CompletableFuture & Asynchronous Programming

61. How do you handle multiple futures with an action when all tasks are completed?

Use thenCombine() with a set of futures to perform an action once all are completed:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
task1.thenCombine(task2, (result1, result2) -> result1 + " and " + result2)
    .thenAccept(System.out::println);
        

62. How do you handle the scenario where multiple futures return the same type of result and need to be combined?

Use thenCombine() when you need to combine two futures of the same type:

CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() -> 1);
CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> 2);
task1.thenCombine(task2, Integer::sum)
    .thenAccept(result -> System.out.println("Sum: " + result));
        

63. How can you apply multiple transformations to a result asynchronously?

Use thenApply() to apply transformations:

CompletableFuture.supplyAsync(() -> "Task 1")
    .thenApply(result -> result + " transformed")
    .thenApply(result -> result + " again")
    .thenAccept(System.out::println);
        

64. How can you handle a timeout for an asynchronous task with a custom exception?

Use completeOnTimeout() with a custom exception:

CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(5000); } catch (InterruptedException e) { }
    return "Task completed";
})
.completeOnTimeout("Timeout Exception", 2, TimeUnit.SECONDS)
.thenAccept(System.out::println);
        

65. How do you execute a task after multiple futures complete?

Use thenRun() to execute after multiple futures:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.allOf(task1, task2)
    .thenRun(() -> System.out.println("All tasks completed"));
        

66. How do you chain multiple futures and perform an action when any of them completes?

Use CompletableFuture.anyOf() to execute on any task completion:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.anyOf(task1, task2)
    .thenAccept(result -> System.out.println("First completed: " + result));
        

67. How can you create a CompletableFuture from an existing value?

Use completedFuture() to create a future from a value:

CompletableFuture<String> future = CompletableFuture.completedFuture("Already Completed");
future.thenAccept(System.out::println);
        

68. How do you combine multiple futures and handle the exception for all of them?

Use exceptionally() for exception handling in combined futures:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture.allOf(task1, task2)
    .exceptionally(ex -> {
        System.out.println("Exception: " + ex.getMessage());
        return null;
    });
        

69. How can you use CompletableFuture to execute multiple tasks concurrently?

Use multiple supplyAsync() calls to execute tasks concurrently:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
task1.thenAccept(System.out::println);
task2.thenAccept(System.out::println);
        

70. How do you apply a function to the result of a completed CompletableFuture?

Use thenApply() to apply a function:

CompletableFuture.supplyAsync(() -> "Task completed")
    .thenApply(result -> result + " and transformed")
    .thenAccept(System.out::println);
        

 

Set 8: CompletableFuture & Asynchronous Programming

71. How do you combine multiple asynchronous tasks and get the first successful result?

Use anyOf() to get the first successful result:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Result from Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Result from Task 2");
CompletableFuture.anyOf(task1, task2)
    .thenAccept(result -> System.out.println("First completed: " + result));
        

72. How can you handle multiple CompletableFutures in a sequential manner?

Use thenCompose() to handle futures sequentially:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
task1.thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Task 2"))
    .thenAccept(System.out::println);
        

73. How do you run a task in a different thread pool using CompletableFuture?

Use the Executor parameter in supplyAsync() to run a task in a different thread pool:

Executor executor = Executors.newFixedThreadPool(2);
CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Task executed in custom thread pool", executor);
task.thenAccept(System.out::println);
        

74. How can you perform an action on the result of a CompletableFuture but without affecting its result?

Use thenAccept() to perform an action without changing the result:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Task completed");
task.thenAccept(result -> System.out.println("Processed: " + result));
        

75. How do you handle an exception in a CompletableFuture chain?

Use exceptionally() to handle exceptions:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException("Something went wrong");
});
task.exceptionally(ex -> "Default value due to exception: " + ex.getMessage())
    .thenAccept(System.out::println);
        

76. How can you block and get the result of a CompletableFuture?

Use get() to block and retrieve the result:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Task result");
String result = task.get();
System.out.println(result);
        

77. How do you schedule a CompletableFuture to run after a delay?

Use completeOnTimeout() to schedule a delayed execution:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Delayed task");
task.completeOnTimeout("Timeout result", 2, TimeUnit.SECONDS)
    .thenAccept(System.out::println);
        

78. How can you ensure a task executes after a certain amount of time?

Use delayedExecutor() to execute a task after a delay:

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Delayed task", executor);
task.completeOnTimeout("Completed after timeout", 2, TimeUnit.SECONDS)
    .thenAccept(System.out::println);
        

79. How can you chain tasks to run only when all previous tasks complete?

Use thenCompose() to chain tasks sequentially, ensuring one task starts after the previous one finishes:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "First task");
task1.thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Second task"))
    .thenAccept(System.out::println);
        

80. How do you run a task when a CompletableFuture is completed regardless of success or failure?

Use whenComplete() to run after completion:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Completed task");
task.whenComplete((result, ex) -> {
    if (ex != null) {
        System.out.println("Error: " + ex.getMessage());
    } else {
        System.out.println("Result: " + result);
    }
});
        

 

Set 9: CompletableFuture & Asynchronous Programming

81. How do you run tasks asynchronously and combine the results?

Use thenCombine() to run two tasks in parallel and combine their results:

CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> 20);
task1.thenCombine(task2, (result1, result2) -> result1 + result2)
    .thenAccept(System.out::println);
        

82. How can you perform a task only after a CompletableFuture has been completed?

Use thenRun() to perform a task after the CompletableFuture completes:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Task completed");
task.thenRun(() -> System.out.println("Post-task action executed"));
        

83. How do you create a CompletableFuture that returns a constant value?

Use completedFuture() to create a CompletableFuture with a predefined result:

CompletableFuture<String> task = CompletableFuture.completedFuture("Constant Value");
task.thenAccept(System.out::println);
        

84. How can you wait for a collection of CompletableFutures to complete?

Use allOf() to wait for all tasks to finish:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture<Void> allTasks = CompletableFuture.allOf(task1, task2);
allTasks.thenRun(() -> System.out.println("All tasks completed"));
        

85. How do you run a task asynchronously after a previous task completes?

Use thenCompose() to run a task asynchronously after another task completes:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1 completed");
task1.thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Task 2"))
    .thenAccept(System.out::println);
        

86. How can you get a result from a CompletableFuture with a timeout?

Use get() with a timeout parameter:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Completed after delay");
String result = task.get(2, TimeUnit.SECONDS);
System.out.println(result);
        

87. How do you handle a cancellation of a CompletableFuture?

Use cancel() to cancel a CompletableFuture:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(5000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
    return "Completed";
});
task.cancel(true);
System.out.println("Task canceled: " + task.isCancelled());
        

88. How can you run a task asynchronously that produces a result and use it in the next step?

Use thenApply() to transform the result of an asynchronous task:

CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> 10);
task.thenApply(result -> result * 2)
    .thenAccept(System.out::println);
        

89. How can you run tasks asynchronously and handle any exceptions?

Use handle() to process results or handle exceptions:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> {
    if (true) throw new RuntimeException("Error!");
    return "Completed successfully";
});
task.handle((result, ex) -> {
    if (ex != null) {
        System.out.println("Error: " + ex.getMessage());
    } else {
        System.out.println("Result: " + result);
    }
});
        

90. How can you create a CompletableFuture chain with multiple stages?

Use a combination of thenApply() and thenAccept() to create a chain of operations:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Task 1");
task.thenApply(result -> result + " -> Task 2")
    .thenApply(result -> result + " -> Task 3")
    .thenAccept(System.out::println);
        

 

Set 10: CompletableFuture & Asynchronous Programming

91. How do you handle multiple independent tasks with a common final result?

Use thenCombine() to handle multiple independent tasks:

CompletableFuture<Integer> task1 = CompletableFuture.supplyAsync(() -> 1);
CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> 2);
task1.thenCombine(task2, (result1, result2) -> result1 + result2)
    .thenAccept(System.out::println);
        

92. How do you create a CompletableFuture that runs a callback only after a task completes?

Use thenAccept() to run a callback after a task finishes:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Task Result");
task.thenAccept(result -> System.out.println("Callback executed with: " + result));
        

93. How can you create a task that runs after a certain delay?

Use delay with sleep() inside a CompletableFuture:

CompletableFuture<String> delayedTask = CompletableFuture.supplyAsync(() -> {
    try { Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
    return "Delayed Task Result";
});
delayedTask.thenAccept(System.out::println);
        

94. How can you execute tasks sequentially in an asynchronous manner?

Use thenCompose() to chain tasks sequentially:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Start");
task1.thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " -> Next"))
    .thenAccept(System.out::println);
        

95. How do you handle multiple tasks that can run independently?

Use allOf() to handle multiple independent tasks:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
CompletableFuture<Void> allTasks = CompletableFuture.allOf(task1, task2);
allTasks.thenRun(() -> System.out.println("Both tasks are completed"));
        

96. How do you run a task asynchronously and return a result in a non-blocking way?

Use supplyAsync() to run tasks asynchronously and return a result:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> "Task completed");
task.thenAccept(result -> System.out.println("Result: " + result));
        

97. How do you create a CompletableFuture chain with error handling?

Use exceptionally() to handle errors in the chain:

CompletableFuture<String> task = CompletableFuture.supplyAsync(() -> {
    if (true) throw new RuntimeException("Error occurred");
    return "Task Result";
});
task.exceptionally(ex -> "Error handled: " + ex.getMessage())
    .thenAccept(System.out::println);
        

98. How can you combine multiple futures and continue with one final result?

Use thenCombine() for combining futures:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 100);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 200);
future1.thenCombine(future2, (result1, result2) -> result1 + result2)
    .thenAccept(System.out::println);
        

99. How do you use runAsync to execute a task without needing a result?

Use runAsync() when you don’t need a result:

CompletableFuture.runAsync(() -> System.out.println("Task completed without a result"));
        

100. How can you combine multiple asynchronous tasks with a success handler?

Use thenApply() to handle successful results:

CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task 1");
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task 2");
task1.thenCombine(task2, (result1, result2) -> result1 + " & " + result2)
    .thenApply(result -> "Combined Result: " + result)
    .thenAccept(System.out::println);